﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotSpatial.Controls;
using DotSpatial.Topology;
using GisContour;

using System.Drawing;
using DotSpatial.Symbology;

namespace HAGISV2
{
    public class Map6IsolineLayer:MapLineLayer
    {
        public Map6IsolineLayer():base()
        {
            this.layer = new ContourLayer();
        }

        # region 显示属性


        # region 标注属性

        
        private bool _isShowLabel = true;

        /// <summary>
        /// 是否显示标注
        /// </summary>
        public bool IsShowLabel
        {
            get { return _isShowLabel; }
            set { _isShowLabel = value; }
        }


        private Color _labelColor = System.Drawing.Color.Black;  //标注颜色设置

        /// <summary>
        /// 标注颜色
        /// </summary>
        public Color LabelColor
        {
            get { return _labelColor; }
            set { _labelColor = value; }
        }


        private System.Drawing.Font _labelFont = new Font("Times New Roman", 12.0F); //图例Font

        /// <summary>
        /// 标注字体
        /// </summary>
        public System.Drawing.Font LabelFont
        {
            get { return _labelFont; }
            set { _labelFont = value; }
        }

        private bool _isLabelTextFormat = false;

        /// <summary>
        /// 标注字符串是否格式化
        /// </summary>
        public bool IsLabelTextFormat
        {
            get { return _isLabelTextFormat; }
            set
            {
                _isLabelTextFormat = value;               

            }
        }

        private Int64 _lableFormatNum = 2; //等值线标注小数点位数

        /// <summary>
        /// //等值线标注小数点位数
        /// </summary>
        public Int64 LableFormatNum
        {
            get { return _lableFormatNum; }
            set
            {
                _lableFormatNum = value;               
            }
        }

        private int _stepNum = 20; //标注间距为20个网格

        /// <summary>
        /// 标注间距为20个网格
        /// </summary>
        public int StepNum
        {
            get { return _stepNum; }
            set
            {
                _stepNum = value;
                if (this.layer != null)
                {
                    this.layer.StepNum = value;
                    this.layer.CalLabel();
                }
            }
        }

        private int _labelNum = 20;  //标注个数最大为10个

        /// <summary>
        /// //标注个数最大为10个
        /// </summary>
        public int LabelNum
        {
            get { return _labelNum; }
            set
            {
                _labelNum = value;
                if (this.layer != null)
                {
                    this.layer.LabelNum = value;
                    this.layer.labelPath = new Dictionary<double, List<Coordinate>>();
                    for (int i = 0; i < this._contourLineList.Count; i++)
                    {                        
                        this.layer.labelPath.Add(this._contourLineList[i].ContourLineValue, new List<Coordinate>());
                    }
                    this.layer.CalLabel();
                }
            }
        }


        # endregion


        # region 面属性

        private bool _isShowContourFill = true;  //是否显示添充

        /// <summary>
        /// 是否显示添充
        /// </summary>
        public bool IsShowContourFill
        {
            get { return _isShowContourFill; }
            set { _isShowContourFill = value; }
        }

        # endregion


        # region 线属性

        private bool _isLineVisble = true;  //是否显示等值线

        /// <summary>
        /// 是否显示线
        /// </summary>
        public bool IsLineVisble
        {
            get { return _isLineVisble; }
            set { _isLineVisble = value; }
        }


        private int _lineWidth = 1; //线宽

        /// <summary>
        /// 线宽（统一设置）
        /// </summary>
        public int LineWidth
        {
            get { return _lineWidth; }
            set { _lineWidth = value; }
        }


        private Color _lineColor = Color.Black;  //线颜色。是统一设置还是可渐变设置？？？？？

        /// <summary>
        /// 线颜色（统一设置）
        /// </summary>
        public Color LineColor
        {
            get { return _lineColor; }
            set { _lineColor = value; }
        }



        # endregion


        # region 图例属性

        private bool _IsShowLegend = true;

        /// <summary>
        /// 是否显示图例
        /// </summary>
        public bool IsShowLegend
        {
            get { return _IsShowLegend; }
            set
            {
                _IsShowLegend = value;
            }
        }

        private System.Drawing.Font _legendFont = new Font("Times New Roman", 8.0F);

        /// <summary>
        /// 图例字体
        /// </summary>
        public System.Drawing.Font LegendFont
        {
            get { return _legendFont; }
            set { _legendFont = value; }
        }

        private System.Drawing.Color _legendColor = System.Drawing.Color.Red;

        /// <summary>
        /// 图例颜色
        /// </summary>
        public System.Drawing.Color LegendColor
        {
            get { return _legendColor; }
            set { _legendColor = value; }
        }

        private bool _IsLegendTextFormat = false;

        /// <summary>
        /// 是否启用图例文本格式化
        /// </summary>
        public bool IsLegendTextFormat
        {
            get { return _IsLegendTextFormat; }
            set { _IsLegendTextFormat = value; }
        }

        private int _LegendFormatNum = 1;

        /// <summary>
        /// 图例小数点位数
        /// </summary>
        public int LegendFormatNum
        {
            get { return _LegendFormatNum; }
            set { _LegendFormatNum = value; }
        }

        private double _LegendOffsetX = 0; //

        /// <summary>
        /// 图例X方向偏移量
        /// </summary>
        public double LegendOffsetX
        {
            get { return _LegendOffsetX; }
            set { _LegendOffsetX = value; }
        }

        private double _LegendOffsetY = 0;

        /// <summary>
        /// 图例Y方向偏移量
        /// </summary>
        public double LegendOffsetY
        {
            get { return _LegendOffsetY; }
            set { _LegendOffsetY = value; }
        }

        private Color _legendBackColor = Color.White;

        /// <summary>
        /// 背景颜色
        /// </summary>
        public Color LegendBackColor
        {
            get { return _legendBackColor; }
            set { _legendBackColor = value; }
        }

        private float _legendWidth = 10.0f;

        /// <summary>
        /// 图例宽度
        /// </summary>
        public float LegendWidth
        {
            get { return _legendWidth; }
            set { _legendWidth = value; }
        }

        private float _legendHeight = 0.5f;

        /// <summary>
        /// 图例高占窗口的百分比
        /// </summary>
        public float LegendHeight
        {
            get { return _legendHeight; }
            set { _legendHeight = value; }
        }

        # endregion

        private bool _useLayerLegend = false;

        public bool UseLayerLegend
        {
            get { return _useLayerLegend; }
            set
            {
                _useLayerLegend = value;

            }
        }

        private double _opacity = 1.0;

        public double Opacity
        {
            get { return _opacity; }
            set 
            {
                if (value > 1) value = 1;
                if (value < 0) value = 0;
                _opacity = value; 

            }
        }


        # endregion

        
        #region 数据属性


        Coordinate[,] _gridCoordinates;

        /// <summary>
        /// 网格点坐标
        /// </summary>
        public Coordinate[,] GridCoordinates
        {
            set { _gridCoordinates = value; }
        }


        double _rotation;

        /// <summary>
        /// 网格倾斜角
        /// </summary>
        public double Rotation
        {
            set { _rotation = value; }
        }

        int[,] _iBound;

        /// <summary>
        /// 单个网格是否可见
        /// </summary>
        public int[,] IBound
        {
            set { _iBound = value; }
        }


        double[,] _data;

        /// <summary>
        /// 网络点值
        /// </summary>
        public double[,] Data
        {
            set { _data = value; }
        }


        //是否要重新绘制
        private bool _isRedraw = false;

        /// <summary>
        /// 封装要绘制的等值线值及此值对应的线颜色、添充颜色
        /// </summary>
        List<ContourLine> _contourLineList = new List<ContourLine>();

        public List<ContourLine> ContourLineList
        {
            get { return _contourLineList; }
            set
            {
                _contourLineList = value;

                if (this.layer != null)
                {
                    this.layer.ContourLineList = value;

                    this._isRedraw = true;

                }
            }
        }


        #endregion


        GisContour.ContourLayer layer;


        #region 外部调用方法，设置网格坐标、网格点值、单个网络是否可见以及网格倾斜角等数据
        


        /// <summary>
        /// 设置数据
        /// </summary>
        /// <param name="leftBotCoor"></param>
        /// <param name="GridData"></param>
        /// <param name="Boundary"></param>
        /// <param name="stepX"></param>
        /// <param name="stepY"></param>
        /// <param name="GridAngle"></param>
        public bool SetData(Coordinate[,] gridCoordinates, double[,] GridData, int[,] Boundary, double GridAngle , bool isCenterBoundary)
        {

            if (gridCoordinates == null || GridData == null || Boundary == null)
            {
                this._gridCoordinates = gridCoordinates;
                this._data = GridData;
                this._rotation = GridAngle;
                return false;
            }

            if (isCenterBoundary == false)
            {
                int[,] newBoundary = new int[Boundary.GetLength(0) - 1, Boundary.GetLength(1) - 1];
                for (int i = 0; i < Boundary.GetLength(0) - 1; i++)
                {
                    for (int j = 0; j < Boundary.GetLength(1) - 1; j++)
                    {
                        if (Boundary[i, j] == 0 || Boundary[i + 1, j] == 0 || Boundary[i, j + 1] == 0 || Boundary[i + 1, j + 1] == 0)
                        {
                            newBoundary[i, j] = 0;
                        }
                        else
                        {
                            newBoundary[i, j] = 1;
                        }
                    }
                }
                this._iBound = newBoundary;
            }
            else
            {
                this._iBound = Boundary;
            }

            this._gridCoordinates = gridCoordinates;
            this._data = GridData;          
            this._rotation = GridAngle;


            this.layer.SetData(this._gridCoordinates, this._data, this._iBound,  this._rotation);

            return true;
        }

        # endregion



        # region 绘制方法函数

        public override void DrawRegions(MapArgs args, List<DotSpatial.Data.Extent> regions)
        {
            base.DrawRegions(args, regions);

            if (regions[0].Width < 0.1) return;
            if (regions[0].Width > 700000) return;

            if (args.Dx > 100000 || args.Dx < 0.001) return;  

            if (this._contourLineList == null || this._contourLineList.Count == 0) return;
            if (this._data == null) return;

            if (this._isRedraw == true)
            {
                this.layer.polyPath = new Dictionary<double, List<List<PointF>>>();
                this.layer.linePath = new Dictionary<double, List<List<PointF>>>();
                this.layer.labelPath = new Dictionary<double, List<Coordinate>>();

                for (int i = 0; i < this._contourLineList.Count; i++)
                {
                    this.layer.polyPath.Add(this._contourLineList[i].ContourLineValue, new List<List<PointF>>());
                    this.layer.linePath.Add(this._contourLineList[i].ContourLineValue, new List<List<PointF>>());
                    this.layer.labelPath.Add(this._contourLineList[i].ContourLineValue, new List<Coordinate>());
                }
                
                //是否开始重新计算
                ComputeIsolines(args);
            }

            this._isRedraw = false;

            //上面是计算

            //开始绘制

            try
            {

                //绘制面
                if (this._isShowContourFill == true)
                {
                    this.DrawPolygon(args);
                }


                //绘制线
                if (this._isLineVisble == true)
                {
                    this.DrawLine(args);
                }

                //绘制标注
                if (this._isShowLabel == true)
                {
                    this.DrawLabel(args);
                }

                if (this.UseLayerLegend == true)
                {
                    this.DrawLegend(args);
                }

                //for (int i = 0; i < this._data.GetLength(0); i++)
                //{
                //    for (int j = 0; j < this._data.GetLength(1); j++)
                //    {
                //        System.Drawing.Point pt = args.ProjToPixel(this._gridCoordinates[i, j]);
                //        args.Device.DrawString(this._data[i, j].ToString(), this._labelFont, Brushes.Black, pt);
                //    }
                //}


            }
            catch (Exception ex)
            { 
            }

        }

        /// <summary>
        /// 刘加，绘制面
        /// </summary>
        /// <param name="args"></param>
        private void DrawPolygon(MapArgs args)
        {
            System.Drawing.Graphics g = args.Device ?? Graphics.FromImage(this.BackBuffer);

            for (int i = 0; i < this._contourLineList.Count; i++)
            {
                for (int j = 0; j < this.layer.polyPath[this._contourLineList[i].ContourLineValue].Count; j++)
                {
                    List<PointF> pts = new List<PointF>();
                    for (int k = 0; k < this.layer.polyPath[this._contourLineList[i].ContourLineValue][j].Count; k++)
                    {
                        pts.Add(args.ProjToPixel(new Coordinate(this.layer.polyPath[this._contourLineList[i].ContourLineValue][j][k].X,
                            this.layer.polyPath[this._contourLineList[i].ContourLineValue][j][k].Y)));
                    }
                    g.FillPolygon(new SolidBrush(this._contourLineList[i].ContourLineFillColor), pts.ToArray());
                }

            }
        }


        /// <summary>
        /// 刘加，绘制等值线的线
        /// </summary>
        /// <param name="args"></param>
        private void DrawLine(MapArgs args)
        {
            System.Drawing.Graphics g = args.Device ?? Graphics.FromImage(this.BackBuffer);

            for (int i = 0; i < this._contourLineList.Count; i++)
            {
                //绘制
                Color lineColor = this._lineColor; // Color.FromArgb((int)(this._opacity * 255), this._contourLineList[i].ContourLineColor); //加透明度的颜色
                System.Drawing.Pen pen = new Pen(lineColor, (float)(this._lineWidth));

                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                for (int j = 0; j < this.layer.linePath[this._contourLineList[i].ContourLineValue].Count; j++)
                {
                  
                        List<System.Drawing.Point> pts = new List<System.Drawing.Point>();
                        for (int k = 0; k < this.layer.linePath[this._contourLineList[i].ContourLineValue][j].Count; k++)
                        {
                            System.Drawing.Point pt = args.ProjToPixel(new Coordinate(this.layer.linePath[this._contourLineList[i].ContourLineValue][j][k].X,
                                this.layer.linePath[this._contourLineList[i].ContourLineValue][j][k].Y));
                            pts.Add(pt);
                        }

                        if (this.IsShowContourFill == false)
                            pen = new Pen(this.ContourLineList[i].ContourLineColor, (float)this.LineWidth);
                        g.DrawLines(pen, pts.ToArray());                  
                }
            }
        }

        /// <summary>
        /// 刘加,绘制标注
        /// </summary>
        /// <param name="args"></param>
        private void DrawLabel(MapArgs args)
        {
            System.Drawing.Graphics g = args.Device ?? Graphics.FromImage(this.BackBuffer);

            

            //加上透明度的标注颜色
            //Color labelColor = Color.FromArgb((int)(this._opacity * 255), this._labelColor);

            for (int i = 0; i < this._contourLineList.Count; i++)
            {
                //字符串格式
                string str = "";
                if (this._isLabelTextFormat == false)
                {
                    str = this._contourLineList[i].ContourLineValue.ToString();
                }
                else
                {
                    str = this._contourLineList[i].ContourLineValue.ToString("E" + this._lableFormatNum.ToString());
                }

                //字符串大小长短
                SizeF size = g.MeasureString(str, this._labelFont);

                for (int j = 0; j < this.layer.labelPath[this._contourLineList[i].ContourLineValue].Count; j++)
                {
                    //转换坐标
                    PointF pt = args.ProjToPixel(this.layer.labelPath[this._contourLineList[i].ContourLineValue][j]);

                    Font labelFont = new Font(this._labelFont.FontFamily, (float)(this._labelFont.Size * args.Dx));   //这是采用随视图变化标注大小变化的方法
                    labelFont = new Font(this._labelFont.FontFamily, this._labelFont.Size);  //这是不随视图变化标注大小不变化的方法，如果用上面的方法，把这句注销即可

                    //旋转角度
                    double txtHeight = g.MeasureString(str, labelFont).Height;
                    double txtWidth = g.MeasureString(str, labelFont).Width;
                    System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix();


                    myMatrix.RotateAt((float)this.layer.labelPath[this._contourLineList[i].ContourLineValue][j].Z, pt);
                    myMatrix.Translate((float)txtWidth / (-2), (float)txtHeight / (-2));

                    System.Drawing.Drawing2D.GraphicsContainer graContainer;
                    graContainer = g.BeginContainer();

                    try
                    {
                        g.Transform = myMatrix;

                        g.DrawString(str, labelFont, new SolidBrush(this._labelColor), pt.X, pt.Y);

                       
                    }
                    catch
                    {

                    }
                    g.EndContainer(graContainer);
                }
            }

           
        }


        /// <summary>
        /// 计算等值线:计算结果包括面、线、标注
        /// </summary>
        /// <param name="args"></param>
        void ComputeIsolines(MapArgs args)
        {
            this.layer.Cal(args);
        }

        /// <summary>
        /// 绘制图例
        /// </summary>
        /// <param name="args"></param>
        public void DrawLegend(MapArgs args)
        {

            if (this._contourLineList == null) return;
            if (this._contourLineList.Count <= 0) return;

            if (this._IsShowLegend == false) return;

            System.Drawing.Graphics g = args.Device ?? Graphics.FromImage(this.BackBuffer);


            IMap map = (this.ParentMapFrame() as IMapFrame).Parent as IMap;
            double scaleX = ((double)args.ImageRectangle.Width) / ((double)map.Width);
            double scaleY = ((double)args.ImageRectangle.Height) / ((double)map.Height);

            System.Drawing.Drawing2D.GraphicsContainer container = g.BeginContainer();
            System.Drawing.Drawing2D.Matrix matrix = new System.Drawing.Drawing2D.Matrix();
            matrix.Scale((float)scaleX, (float)scaleY);
            g.Transform = matrix;


            float Xmax = map.Width;  // .Right;
            float Ymax = map.Height;  //.Bottom;
            float Ymin = 0;  // this.m_ParenLManager.CurrentMap.Top;
            float h = (Ymax - Ymin - 20) * this._legendHeight;

            double stepY = h / this._contourLineList.Count;

            //画背景
            PointF f1 = new PointF();
            f1.X = (float)this._LegendOffsetX ; // Xmax - this._legendWidth - 10.0f -
                // (float)g.MeasureString(this._contourLineList[this._contourLineList.Count - 1].ContourLineValue.ToString(), this._legendFont).Width + (float)this._LegendOffsetX;
            f1.Y = Ymin + (float)this._LegendOffsetY;

            PointF f2 = new PointF();
            f2.X = f1.X + this._legendWidth + (float)g.MeasureString(this._contourLineList[this._contourLineList.Count - 1].ContourLineValue.ToString(), this._legendFont).Width;
            f2.Y = f1.Y;

            PointF f3 = new PointF();
            f3.X = f2.X;
            f3.Y = f1.Y + (float)h;

            PointF f4 = new PointF();
            f4.X = f1.X;
            f4.Y = f3.Y;

            Region region = new Region(new RectangleF(f1.X, f1.Y, f3.X - f1.X, f3.Y - f1.Y));

            //g.FillRegion(new SolidBrush(this._legendBackColor), region);


            //直接用屏幕坐标绘制图例
            for (int i = this.ContourLineList.Count - 1; i >= 0; i--)
            {

                //再把绝对坐标转换成系统坐标
                //一个图例由四个点组成
                List<System.Drawing.PointF> PtList = new List<System.Drawing.PointF>();
                PointF pp1 = new PointF();
                pp1.X = f1.X;
                pp1.Y = f1.Y + (float)((this.ContourLineList.Count - i - 1) * stepY);
                PointF pp2 = new PointF((float)(pp1.X + this._legendWidth), (float)(pp1.Y));
                PointF pp3 = new PointF(pp2.X, (float)(pp1.Y + stepY));
                PointF pp4 = new PointF(pp1.X, (float)(pp1.Y + stepY));

                PtList.Add(pp1);
                PtList.Add(pp2);
                PtList.Add(pp3);
                PtList.Add(pp4);

                System.Drawing.SolidBrush brush = new System.Drawing.SolidBrush(Color.FromArgb((int)(255 * this.Opacity), this.ContourLineList[i].ContourLineFillColor));
                //画图例
                g.FillPolygon(brush, PtList.ToArray());
                //边框
                g.DrawPolygon(new Pen(Color.FromArgb((int)(255 * this.Opacity), Color.Black)), PtList.ToArray());
                //画字符串
                if (this._IsLegendTextFormat == true)  //启用图例文本格式化
                    g.DrawString(this.ContourLineList[i].ContourLineValue.ToString("E" + this._LegendFormatNum.ToString()), this._legendFont,
                        new System.Drawing.SolidBrush(Color.FromArgb((int)(255 * this.Opacity), this._legendColor)), pp3.X, pp3.Y - 10.0f);
                else
                    g.DrawString(this.ContourLineList[i].ContourLineValue.ToString(), this._legendFont,
                       new System.Drawing.SolidBrush(Color.FromArgb((int)(255 * this.Opacity), this._legendColor)), pp3.X, pp3.Y - 10.0f);

            }

            g.EndContainer(container);

        }


        #endregion



       



    }
}
